#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>
#include <memory>
#include <vector>
using namespace std;

// 线程的入口函数的参数，并不单单只是内置类型，可以是一个一个的类!
// 我们的返回值信息，也是可以设计在这个类内的，不去使用return ,pthread_exit

void *threadRoutine(void *args)
{
    int num = *static_cast<int *>(args);
    int cnt = 0;
    while (true)
    {
        cout << "线程-" << num << "，正在运行" << endl;
        sleep(1);
        if (cnt == num + 1)
            break;
        cnt++;
    }
    delete (int *)args;
    // 这里返回必须返回一个堆空间的指针，而不是用一个整形强制转换成地址去返回
    // pthread_exit(reinterpret_cast<void*>(num));
    int *res = new int(num);
    cout << "线程-" << num << " 退出，返回值为" << res << " : " << *res << endl;

    pthread_exit(static_cast<void *>(res));
}

void test1()
{
    pthread_t tid[4];
    for (int i = 0; i < 4; i++)
    {
        // for循环内部是被多线程共享的，i的地址只有一个，
        // 当创建多线程后，&i取到的都是同一个地址的内容
        // 每一次循环，i的值都被覆盖式写入
        // *argc时，主线程可能已经i = 4了，导致 num的值都是一样的
        // 我们需要去new 空间进行一个传参，而不能使用栈空间的地址
        // pthread_create(tid + i,nullptr,threadRoutine,&i);

        // 因此要注意多线程下：共享当前进程的大部分的数据，进程地址空间，文件等

        int *num = new int(i + 1);
        pthread_create(tid + i, nullptr, threadRoutine, num);
    }
    void *res = (void *)1;
    for (int i = 0; i < 4; i++)
    {
        pthread_join(tid[i], &res);
        cout << "join : " << static_cast<int *>(res) << endl;
        delete static_cast<int *>(res);
    }
}

/*
    任务计算topK问题
    让4个线程分别计算0-50，0-100，0-150，0-200的和并把结果返回

*/

struct ThreadData
{

public:
    ThreadData(int num, int topK)
        : _num(num), _topK(topK)
    {
        _name = "线程 - " + to_string(num);
    }
    int _num;
    string _name;
    int _topK;
    int _res; // 返回值
    int _errno = 0;
    ;                // 错误码
    string _err_str; // 错误码对应的信息
};

void *threadRoutine2(void *args)
{
    // 线程分离，主线程不需要再进行join
    pthread_detach(pthread_self());
    ThreadData *td = static_cast<ThreadData *>(args);
    int topK = td->_topK;
    int sum = 0;
    for (int i = 1; i <= topK; i++)
    {
        sum += i;
    }
    td->_res = sum;
    cout << td->_name << "完成任务,并退出 " << sum << endl;

    return nullptr;
}

void test_sumK()
{
    int num = 4;
    vector<pthread_t> tids(num);
    vector<shared_ptr<ThreadData>> sp;

    for (int i = 0; i < num; i++)
    {
        // error make_shared<类型>(构造对象的参数列表)，取决于你调用哪个构造函数
        // shared_ptr<类型>(指针 new 类型()) ... 
        // sp.push_back(make_shared<ThreadData>(new ThreadData(i + 1, 50 * (i + 1))));
        
        // sp.push_back(make_shared<ThreadData>(i + 1, 50 * (i + 1)));
        sp.emplace_back((new ThreadData(i + 1, 50 * (i + 1)))); 

        pthread_create(&tids[i], nullptr, threadRoutine2, sp.back().get());
    }

    // for (int i = 0; i < num; i++)
    // {
    //     pthread_join(tids[i], nullptr);
    // }

    // 当线程detach后,等待1s，保证线程都运行完
    sleep(1);

    for (int i = 0; i < num; i++)
    {
        cout << sp[i]->_name << "完成了0 - " << sp[i]->_topK << "的计算任务，res = "  << sp[i]->_res << endl;
    }
}
int main()
{
    test_sumK();
    return 0;
}